﻿using System;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;

namespace RoiControllers
{
    public class URCircle : ShapeBase
    {
        #region 字段|属性
        private float innerRadius;      // 内圆半径
        [Description("圆的最小外接矩形坐标X")]
        public float X { get => _rectangleF.X; set => _rectangleF.X = value; }
        [Description("圆的最小外接矩形坐标Y")]
        public float Y { get => _rectangleF.Y; set => _rectangleF.Y = value; }
        [Description("圆心坐标")]
        public PointF Center
        {
            get => new PointF(_rectangleF.X + _rectangleF.Width / 2, _rectangleF.Y + _rectangleF.Height / 2);
            set => _rectangleF.Location = value;
        }
        [Description("圆形外轮廓半径")]
        public float Radius => Math.Abs(Math.Min(_rectangleF.Width, _rectangleF.Height) / 2);
        [Description("圆形内轮廓半径")]
        public float InnerRadius
        {
            get => innerRadius;
            set => innerRadius = Math.Min(Math.Max(0, Radius), Math.Max(0, value));
        }
        #endregion

        #region 构造函数
        public URCircle() : base()
        {
            Type = ShapeType.Circle;
            Region = new RectangleF(0, 0, 100, 100); // 默认大小
            InnerRadius = 0; // 默认内部半径
        }
        public URCircle(PointF center, float radius) : base()
        {
            Type = ShapeType.Circle;
            Region = new RectangleF(center.X - radius, center.Y - radius, radius * 2, radius * 2);
            InnerRadius = 0; // 默认内部半径
        }
        #endregion

        #region 绘制相关方法
        /// <summary> 绘制外边框 </summary>
        private void DrawBorder(Graphics graphics)
        {
            using (Pen brush = new Pen(BackColor))
            {
                graphics.DrawEllipse(brush, Region);
            }
        }
        /// <summary> 绘制（填充）区域路径 </summary>
        private void DrawRegion(Graphics graphics)
        {
            //计算填充路径区域（外部圆减去内部圆）
            using (GraphicsPath path = new GraphicsPath())
            {
                path.AddEllipse(Region);    //外轮廓
                if (InnerRadius > 0)
                {
                    RectangleF innerRect = new RectangleF(
                        Center.X - InnerRadius,
                        Center.Y - InnerRadius,
                        InnerRadius * 2,
                        InnerRadius * 2);
                    path.AddEllipse(innerRect); //内轮廓
                }
                using (SolidBrush brush = new SolidBrush(Color.FromArgb(Alpha, BackColor)))
                {
                    graphics.FillPath(brush, path);
                }
            }
        }
        /// <summary> 绘制所有手柄 </summary>
        private void DrawHandles(Graphics graphics)
        {
            // 1、右侧外轮廓手柄
            DrawHandle(graphics, (Center.X + Radius), Center.Y);
            // 2、内部圆手柄
            DrawHandle(graphics, (Center.X + InnerRadius), Center.Y);
        }
        /// <summary> 绘制区域中心 </summary>
        private void DrawRegionCenter(Graphics graphics)
        {
            // 1、计算矩形中心坐标
            int centerX = (int)(Region.X + Region.Width / 2);
            int centerY = (int)(Region.Y + Region.Height / 2);
            // 2、线长度大小（根据矩形大小自适应）
            int lineHalfLength = 3;
            // 3、绘制箭头
            using (Pen arrowPen = new Pen(BackColor, BorderWidth))
            {
                // 3.1 水平线
                Point left = new Point(centerX - lineHalfLength, centerY);
                Point right = new Point(centerX + lineHalfLength, centerY);
                graphics.DrawLine(arrowPen, left, right);
                // 3.2 垂直线
                Point top = new Point(centerX, centerY - lineHalfLength);
                Point bottom = new Point(centerX, centerY + lineHalfLength);
                graphics.DrawLine(arrowPen, top, bottom);
            }
        }
        /// <summary> 绘制描述文本 </summary>
        private void DrawDescription(Graphics graphics)
        {
            using (SolidBrush brush = new SolidBrush(Color.LightGreen))
            {
                Font descriptionFont = new Font("Arial", 9);
                string text = $"{Description},半径：{Radius},内外径差{Radius-innerRadius}";
                SizeF maxTextSize = graphics.MeasureString(text, descriptionFont);
                float x = X + Region.Width / 2 - maxTextSize.Width / 2;
                float y = Y + Region.Height / 2 - maxTextSize.Height;
                graphics.DrawString(text, descriptionFont, brush, x, y);
            }
        }
        #endregion

        #region 抽象方法重写
        public override void Move(PointF point)
        {
            X += point.X;
            Y += point.Y;
            LastLocation = point;
            ExecuteMoveCallback();
        }
        public override void Rotate(PointF point)
        {
        }
        public override void Resize(PointF point)
        {
            switch (HandleType)
            {
                // 右侧手柄:调整外部大小
                case ShapeHandleType.Right:
                    RectangleF rect = new RectangleF(
                        Region.X - point.X / 2,
                        Region.Y - point.X / 2,
                        Region.Width + point.X,
                        Region.Height + point.X);
                    Region = rect;
                    InnerRadius = Radius > InnerRadius-10 ? InnerRadius : InnerRadius - 10;
                    break;
                // 内部手柄:调整内部半径
                case ShapeHandleType.Inner:
                    float newInnerRadius = InnerRadius;
                    newInnerRadius += point.X;
                    newInnerRadius = (newInnerRadius + 10) <Radius? newInnerRadius:Radius-10;
                    InnerRadius = newInnerRadius;
                    break;
            }
            ExecuteResizeCallback();
        }
        public override void DrawShapeWithHandle(Graphics graphics)
        {
            //不感兴趣直接绘制
            if (!IsInterest)
            {
                //保留原来颜色
                Color tempBackColor = BackColor;
                BackColor = InterestColor;
                // 1、绘制外轮廓
                DrawBorder(graphics);
                // 2、计算填充路径区域（外部圆减去内部圆）
                DrawRegion(graphics);
                // 3、绘制手柄
                DrawHandles(graphics);
                // 4、绘制形状描述
                DrawDescription(graphics);
                // 5、绘制区域中心
                DrawRegionCenter(graphics);
                // 恢复颜色
                BackColor = tempBackColor;
                return;
            }
           
            if (IsSelected)
            {
                // 1、计算填充路径区域（外部圆减去内部圆）
                DrawRegion(graphics);
                // 2、绘制手柄
                DrawHandles(graphics);
            }
            // 3、绘制外轮廓
            DrawBorder(graphics);
            // 4、绘制形状描述
            DrawDescription(graphics);
            // 5、绘制区域中心
            DrawRegionCenter(graphics);
        }
        public override void DrawHandle(Graphics graphics, float x, float y)
        {
            //1、计算手柄区域
            RectangleF handleRect = new RectangleF(x - HandleSize / 2, y - HandleSize / 2, HandleSize + 2, HandleSize + 2);
            //2、填充区域
            using (SolidBrush brush = new SolidBrush(Color.FromArgb(Alpha * 2, HandleColor)))
            {
                graphics.FillRectangle(brush, handleRect);
            }
            //3、绘制区域边缘
            using (Pen pen = new Pen(HandleColor, BorderWidth))
            {
                graphics.DrawRectangle(pen, Rectangle.Round(handleRect));
            }
        }
        public override void DrawHandle(Graphics graphics, PointF point)
        {
            RectangleF handleRect = new RectangleF(
                point.X - HandleSize / 2, point.Y - HandleSize / 2,
                HandleSize, HandleSize);
            using (SolidBrush brush = new SolidBrush(Color.FromArgb(Alpha * 2, HandleColor)))
            {
                graphics.FillRectangle(brush, handleRect);
            }
            using (Pen pen = new Pen(HandleColor, BorderWidth))
            {
                graphics.DrawRectangle(pen, Rectangle.Round(handleRect));
            }
        }
        public override ShapeHandleType GetHandleType(PointF point)
        {
            // 检查右侧手柄
            Point rightHandle = new Point((int)(Center.X + Radius), (int)Center.Y);
            if (IsInHandle(point, rightHandle))
            {
                return ShapeHandleType.Right;
            }
            // 检查内部手柄
            Point innerHandle = new Point((int)(Center.X + InnerRadius), (int)Center.Y);
            if (IsInHandle(point, innerHandle))
            {
                return ShapeHandleType.Inner;
            }
            return ShapeHandleType.None;
        }
        public override Cursor GetSystemHandleType(PointF point)
        {
            switch (GetHandleType(point))
            {
                case ShapeHandleType.Right:
                case ShapeHandleType.Inner:
                    return Cursors.SizeWE;
                default:
                    return Cursors.SizeAll;
            }
        }
        public override bool IsInRegion(PointF point)
        {
            //手柄不是None必定在区域内，
            return (GetHandleType(point) != ShapeHandleType.None) || IsInBackground(point);
        }
        public override bool IsInBackground(PointF point)
        {
            Point innerHandle = new Point((int)(Center.X + InnerRadius), (int)Center.Y);
            return Region.Contains(point)&& !IsInHandle(point, innerHandle);
        }
        public override bool IsInHandle(PointF inPoint, PointF point)
        {
            int detectionSize = HandleOutSize + 2;
            RectangleF handleRect = new RectangleF(
                point.X - detectionSize / 2, point.Y - detectionSize / 2,
                detectionSize, detectionSize);
            return handleRect.Contains(inPoint);
        }
        public override bool IsInRotateHandle(PointF point)
        {
           return false;
        }
        #endregion

        #region 委托回调方法重写
        public override void ExecuteMoveCallback()
        {
            MoveEvents?.Invoke(this, Center);
        }
        public override void ExecuteRotateCallback()
        {
            RotateEvents?.Invoke(this, Center);
        }
        public override void ExecuteResizeCallback()
        {
            ResizeEvents?.Invoke(this, Center);
        }
        public override void ExecuteAttachCallback()
        {
            AttachEvents?.Invoke(this, Center);
        }
        public override void ExecuteDetachCallback()
        {
            DetachEvents?.Invoke(this, Center);
        }
        public override void ExecuteSelectedCallback()
        {
            SelectedEvents?.Invoke(this, Center);
        }

        #endregion
    }
}
